/*
 * algoritmosPlanificacion.c
 *
 *  Created on: 28/09/2011
 *      Author: utn_so
 */

#include "../../headers/GlobalHeader.h"

extern char* handlerArchivoMapeado;
extern PPD_CHS posicionActualCabezal, posicionAnterior;
extern int32_t contador_msync;
extern struct_config configuracion;
extern int32_t cantidadTotalPedidos;
extern t_log *logger;
extern int32_t discoEstaSubiendo;
extern sem_t *sem_lista;
extern NodoNstep *lista_pedidosnstep;
extern int32_t *sectores;
extern t_Cola *colaPedidos;
extern t_nodoCola * listaNATrabajar;
extern pthread_mutex_t mutexCabezalActual;

PPD_CHS ppd_LBAToCHS(int32_t sectorRecibido){

	PPD_CHS estructuraCHS;
	int32_t cabezalesPorCilindro=0;
	int32_t sectoresPorPista=0;
	int32_t cilindrosTotales=0;
	int32_t temp=0;


	cilindrosTotales=configuracion.Cylinders;
	cabezalesPorCilindro=configuracion.Heads;
	sectoresPorPista=configuracion.Sectors;

	estructuraCHS.cylinder=(sectorRecibido/(sectoresPorPista*cabezalesPorCilindro));

	temp= (sectorRecibido) % ((cabezalesPorCilindro*sectoresPorPista));

	estructuraCHS.head=(sectorRecibido / sectoresPorPista ) % cabezalesPorCilindro;

	estructuraCHS.sector=sectorRecibido % configuracion.Sectors +1;

	return estructuraCHS;
}

int32_t ppd_CHStoLBA(PPD_CHS structRecibido){

	int32_t formula=0;
	int32_t cabezalesPorCilindro=0;
	int32_t sectoresPorPista=0;

	cabezalesPorCilindro=configuracion.Heads;
	sectoresPorPista=configuracion.Sectors;

	formula=((structRecibido.cylinder*cabezalesPorCilindro)+structRecibido.head)*sectoresPorPista+structRecibido.sector-1;

	return formula;
}


void agregaPedidoEnLista(Nodo **lst, t_pedido pedidosAgregar){

	Nodo *aux;

	// creo el nodo a insertar
	Nodo *nuevo=(Nodo*)malloc(sizeof(Nodo));

	nuevo->structPedidos.conexion_pfs_id=pedidosAgregar.conexion_pfs_id;
	nuevo->structPedidos.conexion_ppd_id=pedidosAgregar.conexion_ppd_id;
	nuevo->structPedidos.direccionSector=pedidosAgregar.direccionSector;
	nuevo->structPedidos.lectura_o_escritura=pedidosAgregar.lectura_o_escritura;
	memcpy(nuevo->structPedidos.planificador_id,pedidosAgregar.planificador_id,25);
	memcpy(nuevo->structPedidos.info,pedidosAgregar.info,512);

	nuevo->sig=NULL;

	if( *lst == NULL )
	{
		*lst = nuevo;
	}
	else
	{
		aux = *lst;
		while( aux->sig != NULL )
		{
			aux = aux->sig;
		}

		aux->sig = nuevo;
	}
	//cantidadTotalPedidos++;
}

void agregaPedidoEnListaOrdenada(Nodo **lst, t_pedido pedidosAgregar){
	Nodo *aux, *ant, *nuevo;

	nuevo = (Nodo*)malloc(sizeof(Nodo));

	nuevo->structPedidos.conexion_pfs_id=pedidosAgregar.conexion_pfs_id;
	nuevo->structPedidos.conexion_ppd_id=pedidosAgregar.conexion_ppd_id;
	nuevo->structPedidos.direccionSector=pedidosAgregar.direccionSector;
	nuevo->structPedidos.lectura_o_escritura=pedidosAgregar.lectura_o_escritura;
	memcpy(nuevo->structPedidos.planificador_id,pedidosAgregar.planificador_id,25);
	memcpy(nuevo->structPedidos.info,pedidosAgregar.info,512);

	if( *lst==NULL ){
		nuevo->sig=NULL; // nuevo es primero y ultimo
		*lst=nuevo;      // la lista comienza en nuevo
		//return nuevo;    // retorna el puntero al
	}else{
		if( pedidosAgregar.direccionSector <= (*lst)->structPedidos.direccionSector){
			nuevo->sig = *lst;
			*lst=nuevo;
			//return nuevo;
		}else{
			aux=*lst;
			ant=NULL;

			while( aux!=NULL && aux->structPedidos.direccionSector<pedidosAgregar.direccionSector ){
				ant=aux;
				aux=aux->sig;
			}

			if( aux==NULL ){
				ant->sig=nuevo;
				nuevo->sig=NULL;
			}else{
				ant->sig=nuevo;
				nuevo->sig=aux;
			}
		}


	}


}


//int32_t tamanioLista(NodoNstep **lst){
//	int32_t cantidadElementos=0;
//	NodoNstep *nodoActual;
//
//	nodoActual = *lst;
//
//	while(nodoActual!=NULL){
//		cantidadElementos++;
//		nodoActual=nodoActual->sig;
//	}
//
//	return cantidadElementos;
//}

void borrarPedidoProcesado(t_nodoCola **lst, t_pedido structObtenido) {
	t_nodoCola * aux, *anterior;
	int32_t comparacion_string;

	anterior = NULL;

	for (aux = *lst; aux != NULL; anterior = aux, aux = aux->siguiente) {

		comparacion_string = strcmp(aux->pedido.planificador_id,structObtenido.planificador_id);
		if (((aux->pedido.direccionSector == structObtenido.direccionSector) && (aux->pedido.conexion_ppd_id == structObtenido.conexion_ppd_id)
				&& (aux->pedido.conexion_pfs_id == structObtenido.conexion_pfs_id) && (aux->pedido.lectura_o_escritura == structObtenido.lectura_o_escritura)
				&& (comparacion_string == 0))) {  /* Encontrado */
			if (anterior == NULL) {

				*lst = aux->siguiente;
				if((colaPedidos->frente) == aux){

					if(colaPedidos->frente == colaPedidos->fin)
						colaPedidos->fin=colaPedidos->frente->siguiente;
					colaPedidos->frente=colaPedidos->frente->siguiente;
				}

			} else {

				anterior->siguiente = aux->siguiente;
				if((colaPedidos->fin) == aux){
					colaPedidos->fin=anterior;
				}
			}

			free(aux);

			return;
		}
	}

}

t_pedido CargoLeoInformacion(t_pedido structDelProcesoObtenido){

	PPD_SECTOR_DEVUELVE sectorProcesado;
	t_pedido sectorTerminado;
	int32_t valorEscribirSector=0;

	//Es un pedido de lectura
	if(structDelProcesoObtenido.lectura_o_escritura=='L'){

		sectorProcesado=ppd_leerSector(structDelProcesoObtenido.direccionSector,handlerArchivoMapeado);
		memcpy(sectorTerminado.info,sectorProcesado.bufferSector,512);

	}else{
		//Es un pedido de escritura
		//int32_t ppd_escribirSector(int32_t sectorAEscribir, char* bufferSector,char* handlerArchivoMapeado);
		valorEscribirSector=ppd_escribirSector(structDelProcesoObtenido.direccionSector, structDelProcesoObtenido.info,handlerArchivoMapeado);
	}

	return sectorTerminado;

}

//t_pedido ppd_sstf(Nodo **lst){
//	Nodo *aux;
//	Nodo *primerNodo;
//	aux=*lst;
//	primerNodo=*lst;
//	float tiempoParaComparar=0;
//	float mejorTiempo=0;
//	t_pedido structParaDevolver;
//
//	//Elijo el proceso de la lista con menor tiempo
//	structParaDevolver=aux->structPedidos;
//	mejorTiempo=tiempoEntreSectores(posicionActualCabezal,ppd_LBAToCHS(aux->structPedidos.direccionSector));
//	//Recorro la lista
//	while( aux != NULL ){
//		tiempoParaComparar=tiempoEntreSectores(posicionActualCabezal,ppd_LBAToCHS(aux->structPedidos.direccionSector));
//
//		if(mejorTiempo>tiempoParaComparar){
//			structParaDevolver=aux->structPedidos;
//			mejorTiempo=tiempoEntreSectores(posicionActualCabezal,ppd_LBAToCHS(aux->structPedidos.direccionSector));
//		}
//
//		aux=aux->sig;
//	}
//	return structParaDevolver;
//}

t_pedido ppd_sstf(Nodo **lst){
	Nodo *aux;
	Nodo *primerNodo;
	aux=*lst;
	primerNodo=*lst;
	float tiempoParaComparar=0;
	float mejorTiempo=99999;
	t_pedido structParaDevolver, structEvaluo;

	//le cargo siempre el -1 por si no hay ningun pedido, entonces el proximo sector seria -1.
	structParaDevolver.direccionSector = -1;

	while (aux!= NULL)
	{
		structEvaluo = aux->structPedidos;
		tiempoParaComparar = tiempoEntreSectores(posicionActualCabezal, ppd_LBAToCHS(structEvaluo.direccionSector));
		if (tiempoParaComparar < mejorTiempo)
		{
			mejorTiempo = tiempoParaComparar;
			structParaDevolver = structEvaluo;
		}
		aux = aux->sig;
	}
	return structParaDevolver;
}

PPD_CHS obtenerChsDesdeProceso(Nodo **lst,int32_t procesoID){
	Nodo *aux, *anterior;
	PPD_CHS sectorDevuelto;

	anterior = NULL;


	while(aux != NULL){

		if (aux->structPedidos.conexion_ppd_id == procesoID) { /* Encontrado */

			sectorDevuelto=ppd_LBAToCHS(aux->structPedidos.direccionSector);

		}
		aux=aux->sig;
	}

	return sectorDevuelto;
}

//float tiempoEntreSectores(PPD_CHS sector1,PPD_CHS sector2){
//
//	float tiempoSectores=0;
//	float tiempoQueTardaEntrePistas;
//	float tiempoQueTardaEntreSectores;
//	int32_t tiempoPistas=0;
//	int32_t cantidadTotalSectores;
//	int32_t rpm;
//
//	rpm=configuracion.RPM;
//
//	cantidadTotalSectores=configuracion.Cylinders*configuracion.Sectors;
//
//	tiempoPistas=configuracion.TiempoEntrePistas;
//
//	//Tiempo Entre Sector en ms
//	tiempoSectores=( 60000 / (float)rpm ) / (float)cantidadTotalSectores;
//
//	tiempoQueTardaEntrePistas=(float)(abs(sector1.cylinder-sector2.cylinder)*tiempoPistas);
//
//	tiempoQueTardaEntreSectores=(float)((abs(sector1.sector-sector2.sector))*tiempoSectores);
//
//	return (tiempoQueTardaEntrePistas+tiempoQueTardaEntreSectores);
//
//}

float tiempoEntreSectores(PPD_CHS sector1,PPD_CHS sector2){

	float tiempoSectores=0;
	float tiempoQueTardaEntrePistas;
	float tiempoQueTardaEntreSectores;
	int tiempoPistas=0;
	int cantidadTotalSectores, cantidadPistas, cantidadSectores;
	float rpm;

	rpm=(float)configuracion.RPM;

	cantidadTotalSectores=configuracion.Cylinders*configuracion.Sectors;

	tiempoPistas=configuracion.TiempoEntrePistas;

	//Tiempo Entre Sector en ms
	tiempoSectores=( 60000 / rpm ) / cantidadTotalSectores;

	cantidadPistas = (abs(sector1.cylinder-sector2.cylinder));
	cantidadSectores = diferenciaEntreSectores(sector1,sector2) - cantidadPistas;

	tiempoQueTardaEntrePistas=(float)cantidadPistas*tiempoPistas;

	tiempoQueTardaEntreSectores=(float)cantidadSectores*tiempoSectores;

	return (tiempoQueTardaEntrePistas+tiempoQueTardaEntreSectores);
}

int32_t *SectoresRecorro(PPD_CHS sectorAnterior, PPD_CHS sector)
{
	PPD_CHS copiaPosicionActual = sectorAnterior;
	int32_t *sectores;
	int32_t sectorAgrego, cantidadSectores, current;

	cantidadSectores = diferenciaEntreSectores(copiaPosicionActual, sector);

	current = 0;

	sectores = malloc(sizeof(int32_t)*cantidadSectores);

	//me paro en la misma pista del sector al que quiero llegar
	while (sector.cylinder != copiaPosicionActual.cylinder)
	{
		//si estoy en una pista menor, incremento la pista
		if (sector.cylinder > copiaPosicionActual.cylinder)
		{
			copiaPosicionActual.cylinder = copiaPosicionActual.cylinder + 1;
			sectorAgrego = ppd_CHStoLBA(copiaPosicionActual);
			memcpy(sectores + current, &sectorAgrego, sizeof(int32_t));
			current++;
		}
		//si estoy en una pista mayor, decremento la pista
		else
		{
			copiaPosicionActual.cylinder = copiaPosicionActual.cylinder - 1;
			sectorAgrego = ppd_CHStoLBA(copiaPosicionActual);
			memcpy(sectores + current, &sectorAgrego, sizeof(int32_t));
			current++;
		}
	}

	//una vez que estoy en la pista, recorro hasto llegar al sector
	while (sector.sector != copiaPosicionActual.sector)
	{
		if (sector.sector < copiaPosicionActual.sector)
		{
			while(copiaPosicionActual.sector < configuracion.Sectors)
			{
				copiaPosicionActual.sector = copiaPosicionActual.sector + 1;
				sectorAgrego = ppd_CHStoLBA(copiaPosicionActual);
				memcpy(sectores + current, &sectorAgrego, sizeof(int32_t));
				current++;
			}

			copiaPosicionActual.sector = 1;
			sectorAgrego = ppd_CHStoLBA(copiaPosicionActual);
			memcpy(sectores + current, &sectorAgrego, sizeof(int32_t));
			current++;

		}
		else
		{
			copiaPosicionActual.sector = copiaPosicionActual.sector + 1;
			sectorAgrego = ppd_CHStoLBA(copiaPosicionActual);
			memcpy(sectores + current, &sectorAgrego, sizeof(int32_t));
			current++;
		}
	}
	return sectores;
}

int32_t diferenciaEntreSectores(PPD_CHS sector1,PPD_CHS sector2)
{
	int32_t resultado;

	resultado = abs(sector1.cylinder-sector2.cylinder);

	if(sector1.sector <= sector2.sector)
	{
		resultado = resultado + abs(sector2.sector-sector1.sector);
	}
	else
	{
		resultado = resultado + configuracion.Sectors-sector1.sector + sector2.sector;
	}

	return resultado;
}

void ppd_info(int32_t sector){
	PPD_CHS sectorParaProcesar;

	sectorParaProcesar=ppd_LBAToCHS(sector);

	printf("pista numero: %d ",sectorParaProcesar.cylinder);
	printf("sector numero: %d \n",sectorParaProcesar.sector);

}

int32_t ppd_clean(int32_t sector1,int32_t sector2){
	PPD_CHS sectorObtenido1;
	PPD_CHS sectorObtenido2;
	int32_t i=0;
	int32_t resultado = 0;

	sectorObtenido1=ppd_LBAToCHS(sector1);
	sectorObtenido2=ppd_LBAToCHS(sector2);

	for( i=sector1; i<=sector2; i++){
		resultado = ppd_cleanSector(i)+resultado;
	}

	// Si el resultado tiene el mismo valor que i
	// significa que todos los valores han sido bien limpiados
	if(resultado==i){
		resultado=1;
	}else{
		resultado=0;
	}

	return resultado;
}

int32_t ppd_cleanSector(int32_t sectorParaProcesar){
	//char buffer[512];
	int32_t resultado = 0;

	resultado = ppd_escribirSector(sectorParaProcesar, charLimpio(),handlerArchivoMapeado);

	return resultado;
}

char* charLimpio(){

	char *bufferSector=(char*)malloc(512*sizeof(char));

	memset( bufferSector, '\0', 512 );

	return bufferSector;
}

//void porQueSectoresPaso(int32_t sector1,int32_t sector2){
//	PPD_CHS sectorObtenido1;
//	PPD_CHS sectorObtenido2;
//	int32_t i=0;
//	int32_t a=0;
//	int32_t b=0;
//	int32_t sectorMaximo=0;
//
//	//Sector Extremo
//	//sectorMaximo=(int)getInt("Sectors");
//	sectorMaximo=configuracion.Sectors;
//
//	sectorObtenido1=ppd_LBAToCHS(sector1);
//	sectorObtenido2=ppd_LBAToCHS(sector2);
//
//	//printf("Sectores Recorridos: ");
//	if(sectorObtenido1.cylinder<sectorObtenido2.cylinder){
//		//Si voy de una pista menor a una mayor
//		//printf("Sectores Recorridos: ");
//		for( i=sectorObtenido1.cylinder; i<sectorObtenido2.cylinder; i++){
//			printf("%d:%d, ",i,sectorObtenido1.sector);
//			//posicionActualCabezal=cargoPosActual(i,sectorObtenido1.sector);
//			posicionAnterior = posicionActualCabezal;
//			posicionActualCabezal=cargoPosicionActualDisco(ppd_LBAToCHS(sectorObtenido1.sector));
//		}
//		if(sectorObtenido1.sector<=sectorObtenido2.sector){
//			for( i=sectorObtenido1.sector; i<=sectorObtenido2.sector; i++){
//				if(i==sectorObtenido2.sector){
//					printf("%d:%d",sectorObtenido2.cylinder,i);
//				}else{
//					printf("%d:%d, ",sectorObtenido2.cylinder,i);
//				}
//				//Actualizo posicion cabezal
//				//posicionActualCabezal=cargoPosActual(sectorObtenido2.cylinder,i);
//				posicionActualCabezal=cargoPosicionActualDisco(ppd_LBAToCHS(sectorObtenido2.cylinder));
//			}
//		}else{
//			for( i=sectorObtenido1.sector; i<=sectorMaximo; i++){
//				printf("%d:%d, ",sectorObtenido2.cylinder,i);
//				//posicionActualCabezal=cargoPosActual(sectorObtenido2.cylinder,i);
//				posicionAnterior = posicionActualCabezal;
//				posicionActualCabezal=cargoPosicionActualDisco(ppd_LBAToCHS(sectorObtenido2.cylinder));
//			}
//			for( i=1; i<=sectorObtenido2.sector; i++){
//				if(i==sectorObtenido2.sector){
//					printf("%d:%d",sectorObtenido2.cylinder,i);
//				}else{
//					printf("%d:%d, ",sectorObtenido2.cylinder,i);
//				}
//				//posicionActualCabezal=cargoPosActual(sectorObtenido2.cylinder,i);
//				posicionAnterior = posicionActualCabezal;
//				posicionActualCabezal=cargoPosicionActualDisco(ppd_LBAToCHS(sectorObtenido2.cylinder));
//			}
//
//		}
//		//printf("\n");
//
//	}else{
//		//Voy dentro de la misma pista
//		if(sectorObtenido1.cylinder==sectorObtenido2.cylinder){
//			if(sectorObtenido1.sector<=sectorObtenido2.sector){
//				for( i=sectorObtenido1.sector; i<=sectorObtenido2.sector; i++){
//					if(i==sectorObtenido2.sector){
//						printf("%d:%d",sectorObtenido2.cylinder,i);
//					}else{
//						printf("%d:%d, ",sectorObtenido2.cylinder,i);
//					}
//					//Actualizo posicion cabezal
//					//posicionActualCabezal=cargoPosActual(sectorObtenido2.cylinder,i);
//					posicionAnterior = posicionActualCabezal;
//					posicionActualCabezal=cargoPosicionActualDisco(ppd_LBAToCHS(sectorObtenido2.cylinder));
//				}
//			}else{
//				for( i=sectorObtenido1.sector; i<=sectorMaximo; i++){
//					printf("%d:%d, ",sectorObtenido2.cylinder,i);
//					//posicionActualCabezal=cargoPosActual(sectorObtenido2.cylinder,i);
//					posicionAnterior = posicionActualCabezal;
//					posicionActualCabezal=cargoPosicionActualDisco(ppd_LBAToCHS(sectorObtenido2.cylinder));
//				}
//				for( i=1; i<=sectorObtenido2.sector; i++){
//					if(i==sectorObtenido2.sector){
//						printf("%d:%d",sectorObtenido2.cylinder,i);
//					}else{
//						printf("%d:%d, ",sectorObtenido2.cylinder,i);
//					}
//					//posicionActualCabezal=cargoPosActual(sectorObtenido2.cylinder,i);
//					posicionAnterior = posicionActualCabezal;
//					posicionActualCabezal=cargoPosicionActualDisco(ppd_LBAToCHS(sectorObtenido2.cylinder));
//				}
//
//			}
//
//		}else{
//			//Voy de una pista superior a una inferior
//			a=sectorObtenido1.sector;
//			b=sectorObtenido2.sector;
//
//			// printf("pase por las sig pistas ");
//			//Primero voy de la pista origen a la pista destino
//			for( i=sectorObtenido1.cylinder; i>sectorObtenido2.cylinder; i--){
//				printf("%d:%d, ",i,sectorObtenido1.sector);
//			}
//			if(sectorObtenido1.sector<=sectorObtenido2.sector){
//				for( i=sectorObtenido1.sector; i<=sectorObtenido2.sector; i++){
//					if(i==sectorObtenido2.sector){
//						printf("%d:%d",sectorObtenido2.cylinder,i);
//					}else{
//						printf("%d:%d, ",sectorObtenido2.cylinder,i);
//					}
//					//Actualizo posicion cabezal
//					//posicionActualCabezal=cargoPosActual(sectorObtenido2.cylinder,i);
//					posicionAnterior = posicionActualCabezal;
//					posicionActualCabezal=cargoPosicionActualDisco(ppd_LBAToCHS(sectorObtenido2.cylinder));
//				}
//			}else{
//				for( i=sectorObtenido1.sector; i<=sectorMaximo; i++){
//					printf("%d:%d, ",sectorObtenido2.cylinder,i);
//					//posicionActualCabezal=cargoPosActual(sectorObtenido2.cylinder,i);
//					posicionAnterior = posicionActualCabezal;
//					posicionActualCabezal=cargoPosicionActualDisco(ppd_LBAToCHS(sectorObtenido2.cylinder));
//				}
//				for( i=1; i<=sectorObtenido2.sector; i++){
//					if(i==sectorObtenido2.sector){
//						printf("%d:%d",sectorObtenido2.cylinder,i);
//					}else{
//						printf("%d:%d, ",sectorObtenido2.cylinder,i);
//					}
//					//posicionActualCabezal=cargoPosActual(sectorObtenido2.cylinder,i);
//					posicionActualCabezal = posicionAnterior;
//					posicionActualCabezal=cargoPosicionActualDisco(ppd_LBAToCHS(sectorObtenido2.cylinder));
//				}
//
//			}
//			// printf("\n");
//
//		}
//	}
//	//printf("\n");
//	//posicionActualCabezal=cargoPosActual(sectorObtenido2.cylinder,proximoSector(sectorObtenido2.sector));
//	posicionAnterior = posicionActualCabezal;
//	posicionActualCabezal=cargoPosicionActualDisco(ppd_LBAToCHS(sectorObtenido2.cylinder));
//}

//PPD_CHS cargoPosActual(int32_t cilindro,int32_t sector){
//	PPD_CHS aux;
//	aux.cylinder=cilindro;
//	aux.head=0;
//	aux.sector=sector;
//
//	return aux;
//}
//
//void ppd_trace1(int32_t sector,PPD_CHS posicionActualCabezal){
//	PPD_CHS aux;
//	int sectorProcesado;
//	int posActual=0;
//
//	aux=ppd_LBAToCHS(sector);
//	sectorProcesado=ppd_CHStoLBA(posicionActualCabezal);
//
//	printf("Posición actual: %d:%d \n",posicionActualCabezal.cylinder,posicionActualCabezal.sector);
//	printf("Sector Solicitado: %d:%d \n",aux.cylinder,aux.sector);
//	printf("Sectores Recorridos: ");
//	posActual=ppd_CHStoLBA(posicionActualCabezal);
//	porQueSectoresPaso(posActual,sector);
//	printf("\n");
//	printf("Tiempo consumido: %5.2fms \n",tiempoEntreSectores(posicionActualCabezal,aux));
//	printf("Próximo Sector: %d:%d \n",aux.cylinder,proximoSector(sector));
//
//	//posicionActualCabezal.sector=aux.sector;
//	//posicionActualCabezal=cargoPosicionActualDisco(posicionActualCabezal);
//}
//
//void ppd_trace2(int32_t sector1,int32_t sector2,PPD_CHS posicionActualCabezal){
//	int32_t arrPedidos[2];
//	int32_t i=0;
//	PPD_CHS aux;
//
//	arrPedidos[0]=sector1;
//	arrPedidos[1]=sector2;
//
//	for( i=0; i<2; i++){
//		ppd_trace1(arrPedidos[i],posicionActualCabezal);
//		aux=ppd_LBAToCHS(arrPedidos[i]);
//		posicionActualCabezal=cargoPosicionActualDisco(aux);
//		printf("\n");
//	}
//
//}
//
//void ppd_trace3(int32_t sector1,int32_t sector2,int32_t sector3,PPD_CHS posicionActualCabezal){
//
//	int32_t arrPedidos[3];
//	int32_t i=0;
//	PPD_CHS aux;
//
//	arrPedidos[0]=sector1;
//	arrPedidos[1]=sector2;
//	arrPedidos[2]=sector3;
//
//
//	for( i=0; i<3; i++){
//		ppd_trace1(arrPedidos[i],posicionActualCabezal);
//		aux=ppd_LBAToCHS(arrPedidos[i]);
//		posicionActualCabezal=cargoPosicionActualDisco(aux);
//		printf("\n");
//	}
//
//}
//
//void ppd_trace4(int32_t sector1,int32_t sector2,int32_t sector3,int32_t sector4,PPD_CHS posicionActualCabezal){
//
//	int32_t arrPedidos[4];
//	int32_t i=0;
//	PPD_CHS aux;
//
//	arrPedidos[0]=sector1;
//	arrPedidos[1]=sector2;
//	arrPedidos[2]=sector3;
//	arrPedidos[3]=sector4;
//
//
//	for( i=0; i<4; i++){
//		ppd_trace1(arrPedidos[i],posicionActualCabezal);
//		aux=ppd_LBAToCHS(arrPedidos[i]);
//		posicionActualCabezal=cargoPosicionActualDisco(aux);
//		printf("\n");
//	}
//
//}
//
//void ppd_trace5(int32_t sector1,int32_t sector2,int32_t sector3,int32_t sector4,int32_t sector5,PPD_CHS posicionActualCabezal){
//
//	int32_t arrPedidos[5];
//	int32_t i=0;
//	PPD_CHS aux;
//
//	arrPedidos[0]=sector1;
//	arrPedidos[1]=sector2;
//	arrPedidos[2]=sector3;
//	arrPedidos[3]=sector4;
//	arrPedidos[4]=sector5;
//
//
//	for( i=0; i<5; i++){
//		ppd_trace1(arrPedidos[i],posicionActualCabezal);
//		aux=ppd_LBAToCHS(arrPedidos[i]);
//		posicionActualCabezal=cargoPosicionActualDisco(aux);
//		printf("\n");
//	}
//
//}

int32_t proximoSector(int32_t sector){
	int32_t sectorMaximo=0;
	PPD_CHS estructura;

	estructura=ppd_LBAToCHS(sector);

	//sectorMaximo=(int)getInt("Sectors");
	sectorMaximo=1024;

	if(estructura.sector==sectorMaximo){
		estructura.sector=1;
	}else{
		estructura.sector=estructura.sector+1;
	}

	return estructura.sector;
}

nipc armoNIPC(t_pedido structDelProcesoObtenido){
	nipc nipcArmado;
	char test[512];
	PPD_SECTOR_DEVUELVE sectorDevuelto;


	if(structDelProcesoObtenido.lectura_o_escritura=='L')
	{
		memcpy(structDelProcesoObtenido.info,test,512);
		nipcArmado.type=LECTURA_OK;
		nipcArmado.payloadlength=sizeof(t_pedido);
		nipcArmado.payload=structDelProcesoObtenido;
		sectorDevuelto=ppd_leerSector(structDelProcesoObtenido.direccionSector,handlerArchivoMapeado);
		memcpy(nipcArmado.payload.info,sectorDevuelto.bufferSector,512);
	}else{
		int32_t valorEscritura=0;
		valorEscritura=ppd_escribirSector(structDelProcesoObtenido.direccionSector, structDelProcesoObtenido.info,handlerArchivoMapeado);
		if(valorEscritura==0){
			nipcArmado.type=ESCRITURA_OK;
			contador_msync++;
		}else{
			nipcArmado.type=ESCRITURA_ERROR;
		}
		nipcArmado.payloadlength=sizeof(t_pedido);
		nipcArmado.payload=structDelProcesoObtenido;

	}

	return nipcArmado;
}

//t_pedido ppd_nstepscan(NodoNstep **lst,PPD_CHS posicionActualCabezal){
//t_pedido ppd_nstepscan(NodoNstep **lst){
//	t_pedido sectorParaDevolver;
//
//	sectorParaDevolver=(*lst)->pedidos->structPedidos;
//
//	posicionAnterior = posicionActualCabezal;
//	//posicionActualCabezal=cargoPosicionActualDisco(ppd_LBAToCHS(sectorParaDevolver.direccionSector));
//
//	return sectorParaDevolver;
//}

//lista_pedidosnstep

//void agregaPedidoEnListaNstep(NodoNstep **lst, t_pedido pedidosAgregar){
void agregaPedidoEnListaNstep(NodoNstep **lst, t_pedido pedidosAgregar){

	int32_t tamanio=0, inserte=0;
	NodoNstep *puntero1=NULL;
	NodoNstep *puntero2=NULL;

	//Nodo *auxBis=(Nodo*)malloc(sizeof(Nodo));

	//NodoNstep *aux=(NodoNstep*)malloc(sizeof(NodoNstep));


	//Significa que no tiene pedidos asi que agrego en el primer nodo
	if(*lst==NULL){
		NodoNstep *aux=(NodoNstep*)malloc(sizeof(NodoNstep));
		*lst = aux;
		(*lst)->sig = NULL;
		(*lst)->cantidadPedidos=0;
		(*lst)->pedidos=NULL;
		//agregaPedidoEnListaOrdenada(&(*lst)->pedidos,pedidosAgregar);
		agregaPedidoEnLista(&((*lst)->pedidos),pedidosAgregar);
		(*lst)->cantidadPedidos++;
	}else{
		puntero1 = *lst;
		puntero2 = *lst;
		while(inserte == 0){
			if(puntero1->cantidadPedidos<configuracion.tamanioListaScan){
				agregaPedidoEnLista(&(puntero1->pedidos),pedidosAgregar);
				puntero1->cantidadPedidos++;
				inserte = 1;
				/*puntero2 = (*lst)->pedidos;
                                while(puntero2 != NULL){
                                        puntero2 = puntero2.sig;
                                }
                                Nodo *nuevo=(Nodo*)malloc(sizeof(Nodo));
                                puntero2 = nuevo
				 */
			}
			else{
				puntero2 = puntero1;
				puntero1 = puntero1->sig;
				if(puntero1 == NULL){
					NodoNstep *nuevo=(NodoNstep*)malloc(sizeof(NodoNstep));
					nuevo->cantidadPedidos = 0;
					nuevo->pedidos=NULL;
					nuevo->sig=NULL;
					puntero1 = nuevo;
					puntero2->sig = nuevo;
				}

			}
		}

	}

	//cantidadTotalPedidos++;

	sem_post(&sem_lista);

}


void borrarPedidoProcesadonstep(NodoNstep **lst){

	NodoNstep *ptr1=NULL;
	NodoNstep *ptr2=NULL;

	ptr1=*lst;
	*lst=(*lst)->sig;

	//ptr1=ptr1->sig;
	free(ptr1);
	//      NodoNstep *auxnstep=NULL;
	//      Nodo *aux=NULL;
	//      aux=(*lst)->pedidos;
	//
	//      (*lst)->pedidos=(*lst)->pedidos->sig;
	//      free(aux);
	//
	//      if( (*lst)->pedidos == NULL){
	//
	//              if(*fin_lista_pedidosnstep == *lst) *fin_lista_pedidosnstep = NULL;
	//              auxnstep=*lst;
	//              *lst=(*lst)->sig;
	//              free(auxnstep);
	//      }

	//cantidadTotalPedidos--;
}


//t_pedido ppd_nstepScan(NodoNstep **lst){
//
//	t_pedido elegido;
//	int32_t posicion;
//	posicion=ppd_CHStoLBA(posicionActualCabezal);
//
//	if( (*lst)->cantidadPedidos==1){
//		elegido = (*lst)->pedidos->structPedidos;
//		borrarPedidoProcesado(&((*lst)->pedidos), (*lst)->pedidos->structPedidos);
//		(*lst)->cantidadPedidos--;
//		borrarPedidoProcesadonstep(lst);
//
//		if(elegido.direccionSector<posicion){
//			discoEstaSubiendo=0;
//		}else{
//			if(elegido.direccionSector>posicion){
//			discoEstaSubiendo=1;
//			}
//		}
//
//		return elegido;
//	}else{
//
//		elegido=mejorNstep(lst);
//
//		return elegido;
//	}
//
//}

t_pedido ppd_nstepScan(int32_t N){

	t_pedido elegido;
	int32_t actual;

	pthread_mutex_lock (&mutexCabezalActual);
	actual=ppd_CHStoLBA(posicionActualCabezal);
	pthread_mutex_unlock (&mutexCabezalActual);

	if( N == 1){
		elegido = listaNATrabajar->pedido;

		borrarPedidoProcesado(&listaNATrabajar,listaNATrabajar->pedido);

		sem_wait(&(colaPedidos->cantidadPedidos));

		if(elegido.direccionSector<actual){
			discoEstaSubiendo=0;
		}else{
			if(elegido.direccionSector>actual){
				discoEstaSubiendo=1;
			}
		}


		return elegido;
	}else{

		elegido=mejorNstep(listaNATrabajar,N);
		borrarPedidoProcesado(&listaNATrabajar,elegido);

		sem_wait(&(colaPedidos->cantidadPedidos));

		if(elegido.direccionSector<actual){
			discoEstaSubiendo=0;
		}else{
			if(elegido.direccionSector>actual){
				discoEstaSubiendo=1;
			}
		}

		return elegido;
	}



}

t_pedido mejorNstep(t_nodoCola * lstATrabajar, int32_t N){


	t_nodoCola *aux=NULL;
	t_nodoCola *mejor=NULL;
	t_pedido mejorPedido;
	PPD_CHS mejorSector,auxSector;

	mejor=NULL;

	int32_t posicionActual;
	int32_t cambioSentido=0;

	pthread_mutex_lock (&mutexCabezalActual);
	posicionActual=ppd_CHStoLBA(posicionActualCabezal);
	pthread_mutex_unlock (&mutexCabezalActual);
	int32_t var =0;

	while(cambioSentido==0){
		var =0;
		cambioSentido++;

		if(discoEstaSubiendo==1){
			aux =lstATrabajar;
			while((var<N) && aux!=NULL){

				if(aux->pedido.direccionSector >= posicionActual){
					//Es la primera vez que entra
					if(mejor==NULL){

						mejor=aux;
						mejorSector=ppd_LBAToCHS(aux->pedido.direccionSector);

					}else{

						auxSector=ppd_LBAToCHS(aux->pedido.direccionSector);
							//Debo fijarme el sentido del movimiento
						if( (auxSector.cylinder<=mejorSector.cylinder) && (auxSector.sector<mejorSector.sector)){
									mejor=aux;
									mejorSector=ppd_LBAToCHS(aux->pedido.direccionSector);
								}

					}
				}

				aux=aux->siguiente;
				var++;
			}
			if(mejor==NULL){
				cambioSentido--;
				discoEstaSubiendo=0;
			}

		}else{
			aux =lstATrabajar;
			//Disco baja
			while((var<N) && aux!=NULL){

				if(aux->pedido.direccionSector <= posicionActual){

				if(mejor==NULL){

					mejor=aux;
					mejorSector=ppd_LBAToCHS(aux->pedido.direccionSector);

				}else{
					auxSector=ppd_LBAToCHS(aux->pedido.direccionSector);
					//Misma pista
					if( (auxSector.cylinder>= mejorSector.cylinder)&&(auxSector.sector>mejorSector.sector)){

							mejor=aux;
							mejorSector=ppd_LBAToCHS(aux->pedido.direccionSector);

						}

					}
				}
				var++;
				aux=aux->siguiente;
			}

			if(mejor==NULL){
				cambioSentido--;
				discoEstaSubiendo=1;
			}

		}
	}

	mejorPedido=mejor->pedido;

	return mejorPedido;
}

t_pedido ppd_nstepScanProximoSector(int32_t N)
{
		t_pedido elegido;
		int32_t actual;
		elegido.direccionSector=0;
		pthread_mutex_lock (&mutexCabezalActual);
		actual=ppd_CHStoLBA(posicionActualCabezal);
		pthread_mutex_unlock (&mutexCabezalActual);

	/*	if( N == 1){
			elegido = listaNATrabajar->pedido;

				if(elegido.direccionSector<actual){
					discoEstaSubiendo=0;
				}else{
					if(elegido.direccionSector>actual){
						discoEstaSubiendo=1;
					}
				}
				return elegido;

		}else{*/
			if(N==0){
				elegido=mejorNstep(listaNATrabajar,configuracion.tamanioListaScan);
			}else{
				elegido=mejorNstep(listaNATrabajar,N);
			}

			if(elegido.direccionSector<actual){
				discoEstaSubiendo=0;
			}else{
				if(elegido.direccionSector>actual){
					discoEstaSubiendo=1;
				}
			}

			return elegido;
/*}
		return elegido;*/
}

//t_pedido ppd_nstepScanProximoSector(NodoNstep **lst){
//
//	t_pedido elegido;
//	if(*lst != NULL){
//		if((*lst)->pedidos!=NULL){
//
//			if((*lst)->cantidadPedidos==1){
//				elegido = (*lst)->pedidos->structPedidos;
//				return elegido;
//			}else{
//
//				elegido=mejorNstepProximo(lst);
//
//				return elegido;
//			}
//
//		}else{
//			elegido.direccionSector=-1;
//			return elegido;
//		}
//	}else{
//		elegido.direccionSector=-1;
//		return elegido;
//	}
//
//}


//t_pedido mejorNstep(NodoNstep **lstGrande){
//
//	Nodo *lst=(*lstGrande)->pedidos;
//	Nodo *aux=NULL;
//	Nodo *mejor=NULL;
//	t_pedido mejorPedido;
//
//	mejor=NULL;
//	//aux=lst;
//	int32_t posicionActual;
//	int32_t cambioSentido=0;
//
//	posicionActual=ppd_CHStoLBA(posicionActualCabezal);
//
//	while(cambioSentido==0){
//
//		cambioSentido++;
//		//Disco sube
//		if(discoEstaSubiendo==1){
//			aux = lst;
//			while(aux!=NULL){
//
//				if(aux->structPedidos.direccionSector>posicionActual){
//					if((mejor==NULL) || (aux->structPedidos.direccionSector<=mejor->structPedidos.direccionSector)){
//
//						mejor=aux;
//
//					}
//				}
//
//				aux=aux->sig;
//
//			}
//			if(mejor==NULL){
//				cambioSentido--;
//				discoEstaSubiendo=0;
//			}
//
//		}else{
//			aux = lst;
//			//Disco baja
//			while(aux!=NULL){
//				if(aux->structPedidos.direccionSector<posicionActual){
//					if((mejor==NULL) || (aux->structPedidos.direccionSector>=mejor->structPedidos.direccionSector)){
//
//						mejor=aux;
//
//					}
//				}
//
//				aux=aux->sig;
//
//			}
//			if(mejor==NULL){
//				cambioSentido--;
//				discoEstaSubiendo=1;
//			}
//
//		}
//	}
//	mejorPedido=mejor->structPedidos;
//
//	borrarPedidoProcesado(&((*lstGrande)->pedidos), mejorPedido);
//	(*lstGrande)->cantidadPedidos--;
//
//	if((*lstGrande)->pedidos==NULL){
//		borrarPedidoProcesadonstep(lstGrande);
//	}
//
//	return mejorPedido;
//}

t_pedido mejorNstepProximo(NodoNstep **lstGrande){
	Nodo *lst=(*lstGrande)->pedidos;
	Nodo *aux=NULL;
	Nodo *mejor=NULL;
	t_pedido mejorPedido;
	PPD_CHS mejorSector,auxSector;

	mejor=NULL;
	//aux=lst;
	int32_t posicionActual;
	int32_t cambioSentido=0;

	posicionActual=ppd_CHStoLBA(posicionActualCabezal);

	while(cambioSentido==0){

		cambioSentido++;
		//Disco sube
		if(discoEstaSubiendo==1){
			aux = lst;
			while(aux!=NULL){

				if(aux->structPedidos.direccionSector >= posicionActual){
					//Es la primera vez que entra
					if(mejor==NULL){

						mejor=aux;
						mejorSector=ppd_LBAToCHS(aux->structPedidos.direccionSector);

					}else{
						//Si es el mismo sector me quedo con ese
						if(aux->structPedidos.direccionSector == mejor->structPedidos.direccionSector){
							mejor=aux;
							mejorSector=ppd_LBAToCHS(aux->structPedidos.direccionSector);
						}else{
							auxSector=ppd_LBAToCHS(aux->structPedidos.direccionSector);
							//Debo fijarme el sentido del movimiento
							if( (auxSector.cylinder<=mejorSector.cylinder)){
								if(auxSector.sector<=mejorSector.sector){
									mejor=aux;
									mejorSector=ppd_LBAToCHS(aux->structPedidos.direccionSector);
								}

							}
						}
					}
				}

				aux=aux->sig;

			}
			if(mejor==NULL){
				cambioSentido--;
				discoEstaSubiendo=0;
			}

		}else{
			aux = lst;
			//Disco baja
			while(aux!=NULL){
				auxSector=ppd_LBAToCHS(aux->structPedidos.direccionSector);

				if(mejor==NULL){

					mejor=aux;
					mejorSector=ppd_LBAToCHS(aux->structPedidos.direccionSector);

				}else{
					auxSector=ppd_LBAToCHS(aux->structPedidos.direccionSector);
					//Misma pista
					if( auxSector.cylinder==mejorSector.cylinder ){

						if(auxSector.sector<mejorSector.sector){

							mejor=aux;
							mejorSector=ppd_LBAToCHS(aux->structPedidos.direccionSector);

						}

					}else{

						//pista menor
						if( auxSector.cylinder<posicionActualCabezal.cylinder ){

							if(auxSector.sector<=mejorSector.sector){
								mejor=aux;
								mejorSector=ppd_LBAToCHS(aux->structPedidos.direccionSector);

							}

						}

					}
				}

				aux=aux->sig;
			}

			if(mejor==NULL){
				cambioSentido--;
				discoEstaSubiendo=1;
			}

		}
	}
	mejorPedido=mejor->structPedidos;

	return mejorPedido;


}

